#pragma once
#include <iostream>
#include "../connectinfo.hpp"
/*
 *  * 定义chat服务端的类
 *   * */

class TcpNewConnect
{
  public:
    TcpNewConnect(int newsockfd)
    {
      new_sock_ = newsockfd;

    }

    ~TcpNewConnect()
    {


    }

    int GetNewSockfd()
    {
      return new_sock_;

    }

    void SetThisPointer(void* chatsvr)
    {
      server_ = chatsvr; 

    }

    void* GetThisPointer()
    {
      return server_;

    }
  private:
    int new_sock_;
    void* server_;
    //保存charsvr类的this指针
    //        void* server_;
    //
};


class ChatSvr
{
  public:
    ChatSvr()
    {
      tcp_sockfd_ = -1;
      tcp_port_ = TCPPORT;

    }

    ~ChatSvr()
    {
      if(tcp_sockfd_ >= 0)
      {
        close(tcp_sockfd_);

      }

    }

    /*
     *          * 初始化接口
     *                   * */

    int InitSvr()
    {
      /*
       *              * 1.初始化tcp的socket编程
       *                           *    socket, bind， listen
       *                                        * */
      tcp_sockfd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if(tcp_sockfd_ < 0)
      {
        perror("socket");
        return -1;

      }

      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(tcp_port_);
      addr.sin_addr.s_addr = inet_addr("0.0.0.0");

      int ret = bind(tcp_sockfd_, (struct sockaddr*)&addr, sizeof(addr));
      if(ret < 0)
      {
        perror("bind");
        return -2;

      }

      ret = listen(tcp_sockfd_, 5);
      if(ret < 0)
      {
        perror("listen");
        return -3;

      }

      return 0;

    }

    int StartThread()
    {
      /*
       * 1.接收tcp新连接
       * 创建线程, 为tcp客户端继续服务
       *                                        * */

      while(1)
      {
        struct sockaddr_in peer_addr;
        socklen_t peer_addrlen = sizeof(peer_addr);
        int newsockfd = accept(tcp_sockfd_, (struct sockaddr*)&peer_addr, &peer_addrlen);
        if(newsockfd < 0)
        {
          //继续
          perror("accept");
          printf("continue accept...\n");
          continue;                                                                        
        }

        /*
         * 为新的客户端连接创建线程来进行处理
         * 如何把newsockfd传递给线程的入口函数
         *                                   * */
        TcpNewConnect* tnc = new TcpNewConnect(newsockfd);
        if(tnc == NULL)
        {
          close(newsockfd);
          continue;

        }

        tnc->SetThisPointer((void*)this);

        pthread_t tid;
        int ret = pthread_create(&tid, NULL, RegiAndLoginStart, (void*)tnc);
        if(ret < 0)
        {
          delete tnc;
          close(newsockfd);
          continue;

        }

      }

    }

    static void* RegiAndLoginStart(void* arg)
    {
      pthread_detach(pthread_self());

      TcpNewConnect* tnc = (TcpNewConnect*)arg;
      ChatSvr* cs = (ChatSvr*)(tnc->GetThisPointer());

      int newsockfd = tnc->GetNewSockfd();

      char type = -1;
      while(1)
      {
        ssize_t recv_size = recv(newsockfd, &type, 1, 0);
        if(recv_size < 0)
        {
          continue;

        }
        else if(recv_size == 0)
        {
          close(newsockfd);
          delete tnc;
          pthread_exit(NULL);

        }
        else
        {
          break;

        }

      }

      int ret = -100;
      switch(type)
      {
        case Register:
          {
            ret = cs->DealRegister(newsockfd);
            /* 需要判断了 TODO*/
            break;

          }
        case Login:
          {
            break;

          }
        default:
          break;
          //如何给客户端回复应答
          //            
      }

      struct RespInfo rsp;

      if(ret == RegisterFailed)
      {
        rsp.status_ = RegisterFailed;
        rsp.userid_ = 0;

      }
      else if(ret == RegisterSuccess)
      {
        rsp.status_ = RegisterSuccess;
        rsp.userid_ = 1;

      }

      send(newsockfd, &rsp, sizeof(rsp), 0);

      return NULL;

    }


    int DealRegister(int newsockfd)
    {
      while(1)
      {
        struct RegInfo ri;
        ssize_t recv_size = recv(newsockfd, &ri, sizeof(ri), 0);
        if(recv_size < 0)
        {
          continue;

        }
        else if(recv_size == 0)
        {
          close(newsockfd);
          return -2;

        }
        else
        {
          break;

        }

      }

      return RegisterSuccess;

      /*
       *              * 把客户端注册的数据保存下来
       *                           * TODO
       *                                        * */

    }


  private:
    int tcp_sockfd_;
    uint16_t tcp_port_;

};
